<!DOCTYPE html>



  


<html class="theme-next muse use-motion" lang="zh-Hans">
<head><meta name="generator" content="Hexo 3.8.0">
  <meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<meta name="theme-color" content="#222">









<meta http-equiv="Cache-Control" content="no-transform">
<meta http-equiv="Cache-Control" content="no-siteapp">
















  
  
  <link href="/lib/fancybox/source/jquery.fancybox.css?v=2.1.5" rel="stylesheet" type="text/css">







<link href="/lib/font-awesome/css/font-awesome.min.css?v=4.6.2" rel="stylesheet" type="text/css">

<link href="/css/main.css?v=5.1.4" rel="stylesheet" type="text/css">


  <link rel="apple-touch-icon" sizes="180x180" href="/images/apple-touch-icon-next.png?v=5.1.4">


  <link rel="icon" type="image/png" sizes="32x32" href="/images/favicon-32x32-next.png?v=5.1.4">


  <link rel="icon" type="image/png" sizes="16x16" href="/images/favicon-16x16-next.png?v=5.1.4">


  <link rel="mask-icon" href="/images/logo.svg?v=5.1.4" color="#222">





  <meta name="keywords" content="Hexo, NexT">





  <link rel="alternate" href="/atom.xml" title="renhao" type="application/atom+xml">






<meta name="description" content="详见JavaScript高级程序设计（第3版）第六章面向对象的程序设计（p138-p174）">
<meta property="og:type" content="article">
<meta property="og:title" content="js中的原型链和继承">
<meta property="og:url" content="https://huangrenhao.gitee.io/2019/09/29/js-prototypechain/index.html">
<meta property="og:site_name" content="renhao">
<meta property="og:description" content="详见JavaScript高级程序设计（第3版）第六章面向对象的程序设计（p138-p174）">
<meta property="og:locale" content="zh-Hans">
<meta property="og:updated_time" content="2020-09-25T00:49:50.000Z">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="js中的原型链和继承">
<meta name="twitter:description" content="详见JavaScript高级程序设计（第3版）第六章面向对象的程序设计（p138-p174）">



<script type="text/javascript" id="hexo.configurations">
  var NexT = window.NexT || {};
  var CONFIG = {
    root: '/',
    scheme: 'Muse',
    version: '5.1.4',
    sidebar: {"position":"left","display":"post","offset":12,"b2t":false,"scrollpercent":false,"onmobile":false},
    fancybox: true,
    tabs: true,
    motion: {"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"slideDownIn","post_body":"slideDownIn","coll_header":"slideLeftIn","sidebar":"slideUpIn"}},
    duoshuo: {
      userId: '0',
      author: '博主'
    },
    algolia: {
      applicationID: '',
      apiKey: '',
      indexName: '',
      hits: {"per_page":10},
      labels: {"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}
    }
  };
</script>



  <link rel="canonical" href="https://huangrenhao.gitee.io/2019/09/29/js-prototypechain/">





  <title>js中的原型链和继承 | renhao</title>
  








<link rel="stylesheet" href="/css/prism-tomorrow.css" type="text/css"></head>

<body itemscope="" itemtype="http://schema.org/WebPage" lang="zh-Hans">
  
  
    
  

  <div class="container sidebar-position-left page-post-detail">
    <div class="headband"></div>

    <header id="header" class="header" itemscope="" itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-wrapper">
  <div class="site-meta ">
    

    <div class="custom-logo-site-title">
      <a href="/" class="brand" rel="start">
        <span class="logo-line-before"><i></i></span>
        <span class="site-title">renhao</span>
        <span class="logo-line-after"><i></i></span>
      </a>
    </div>
      
        <p class="site-subtitle"></p>
      
  </div>

  <div class="site-nav-toggle">
    <button>
      <span class="btn-bar"></span>
      <span class="btn-bar"></span>
      <span class="btn-bar"></span>
    </button>
  </div>
</div>

<nav class="site-nav">
  

  
    <ul id="menu" class="menu">
      
        
        <li class="menu-item menu-item-home">
          <a href="/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-home"></i> <br>
            
            首页
          </a>
        </li>
      
        
        <li class="menu-item menu-item-categories">
          <a href="/categories/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-th"></i> <br>
            
            分类
          </a>
        </li>
      
        
        <li class="menu-item menu-item-archives">
          <a href="/archives/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-archive"></i> <br>
            
            归档
          </a>
        </li>
      

      
    </ul>
  

  
</nav>



 </div>
    </header>

    <main id="main" class="main">
      <div class="main-inner">
        <div class="content-wrap">
          <div id="content" class="content">
            

  <div id="posts" class="posts-expand">
    

  

  
  
  

  <article class="post post-type-normal" itemscope="" itemtype="http://schema.org/Article">
  
  
  
  <div class="post-block">
    <link itemprop="mainEntityOfPage" href="https://huangrenhao.gitee.io/2019/09/29/js-prototypechain/">

    <span hidden itemprop="author" itemscope="" itemtype="http://schema.org/Person">
      <meta itemprop="name" content="renhao">
      <meta itemprop="description" content="">
      <meta itemprop="image" content="/images/avatar.gif">
    </span>

    <span hidden itemprop="publisher" itemscope="" itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="renhao">
    </span>

    
      <header class="post-header">

        
        
          <h1 class="post-title" itemprop="name headline">js中的原型链和继承</h1>
        

        <div class="post-meta">
          <span class="post-time">
            
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              
                <span class="post-meta-item-text">发表于</span>
              
              <time title="创建于" itemprop="dateCreated datePublished" datetime="2019-09-29T22:45:54+08:00">
                2019-09-29
              </time>
            

            

            
          </span>

          
            <span class="post-category">
            
              <span class="post-meta-divider">|</span>
            
              <span class="post-meta-item-icon">
                <i class="fa fa-folder-o"></i>
              </span>
              
                <span class="post-meta-item-text">分类于</span>
              
              
                <span itemprop="about" itemscope="" itemtype="http://schema.org/Thing">
                  <a href="/categories/js/" itemprop="url" rel="index">
                    <span itemprop="name">js</span>
                  </a>
                </span>

                
                
              
            </span>
          

          
            
              <span class="post-comments-count">
                <span class="post-meta-divider">|</span>
                <span class="post-meta-item-icon">
                  <i class="fa fa-comment-o"></i>
                </span>
                <a href="/2019/09/29/js-prototypechain/#comments" itemprop="discussionUrl">
                  <span class="post-comments-count valine-comment-count" data-xid="/2019/09/29/js-prototypechain/" itemprop="commentCount"></span>
                </a>
              </span>
            
          

          
          

          

          
            <div class="post-wordcount">
              
                
                <span class="post-meta-item-icon">
                  <i class="fa fa-file-word-o"></i>
                </span>
                
                  <span class="post-meta-item-text">字数统计&#58;</span>
                
                <span title="字数统计">
                  3.9k
                </span>
              

              
                <span class="post-meta-divider">|</span>
              

              
                <span class="post-meta-item-icon">
                  <i class="fa fa-clock-o"></i>
                </span>
                
                  <span class="post-meta-item-text">阅读时长 &asymp;</span>
                
                <span title="阅读时长">
                  14
                </span>
              
            </div>
          

          

        </div>
      </header>
    

    
    
    
    <div class="post-body" itemprop="articleBody">

      
      

      
        <p>详见JavaScript高级程序设计（第3版）第六章面向对象的程序设计（p138-p174）<a id="more"></a></p>
<h3 id="理解对象"><a href="#理解对象" class="headerlink" title="理解对象"></a>理解对象</h3><p>面向对象（OO，Object-Oriented）的语言有一个标志就是它们都有类的概念，通过类可以创建任意多个具有相同属性和方法的对象。</p>
<p>创建新对象实例可以通过<code>new Object()</code>创建实例后给这个实例上的属性赋值或者通过对象字面量语法来创建。</p>
<p>属性类型：描述属性的各种特征，ECMA-262定义这些特性是为了实现JavaScript引擎，在JavaScript中不能直接访问，放在两对儿方括号（表示特性是内部值），也即所说的属性描述符。要修改属性默认的特性只能使用<code>Object.defineProperty()</code>的方法，接收三个参数即属性所在的对象、属性名字和一个或者多个描述符对象。可以多次调用<code>Obeject.defineProperty()</code>修改同一个属性，但在把configurable修改为false（不可配置）之后就不能在把它变回可配置（即再调用<code>Object.defineProperty()</code>修改除writable之外的特性都会导致错误）。读取访问器属性时会调用getter函数（负责返回有效的值），写入访问器属性时会调用setter函数并传入新值（负责决定如何处理数据）。访问器中setter属性常见的使用方式是用于设置一个属性的值会导致其他属性发生变化的情况。只指定<code>getter</code>而不指定<code>setter</code>意味着属性不能写，尝试写入会被忽略；只指定<code>setter</code>而不指定<code>getter</code>也意味着属性不能读，会返回undefined。</p>
<ul>
<li><p>数据属性：</p>
<ul>
<li><code>[[Configurable]]</code>：能否通过<code>delete</code>删除属性从而重新定义属性，能否直接修改属性或者能否把属性修改为访问器属性，默认值为true。</li>
<li><code>[[Enumerable]]</code>：表示能否通过for-in循环返回属性即是否可枚举，默认为true。</li>
<li><code>[[Writable]]</code>：表示能否修改属性的值，默认为true。</li>
<li><code>[[Value]]</code>：包含这个属性的数据值，默认为undefined</li>
</ul>
</li>
<li><p>访问器属性：</p>
<ul>
<li><p><code>[[Configurable]]</code>：能否通过<code>delete</code>删除属性从而重新定义属性，能否直接修改属性或者能否把属性修改为数据属性，默认值为true。</p>
</li>
<li><p><code>[[Enumerable]]</code>：表示能否通过for-in循环返回属性，默认为true。</p>
</li>
<li><code>[[Get]]</code>：在读取属性时调用的函数，默认为undefined</li>
<li><code>[[Set]]</code>：在写入属性时调用的函数，默认为undefined</li>
</ul>
</li>
</ul>
<h3 id="创建对象"><a href="#创建对象" class="headerlink" title="创建对象"></a>创建对象</h3><ol>
<li><p>工厂模式</p>
<p>使用函数来封装以特定接口创建对象的细节，函数接受构建一个对象的所有必要信息的参数，每次调用都会执行一遍这个函数返回一个对象实例，可以创建多个相似对象但没有解决对象识别（即不知道一个对象的类型）。</p>
</li>
<li><p>构造函数模式</p>
<p>相比于工厂模式没有显式地创建对象，直接将属性和方法赋给了this对象，也没有return语句。创建实例的时候需要使用new操作符，这种方式会经历4个步骤：</p>
<ul>
<li>创建一个新对象</li>
<li>将构造函数的作用域赋给新对象（即this指向变为新对象）</li>
<li>执行构造函数中的代码（为这个新对象添加属性）</li>
<li>返回新对象</li>
</ul>
<p>自定义构造函数可以将它的实例标识为一种特定的类型。任何函数只要通过new操作符来调用就可以作为构造函数，如果不使用new操作符调用就和普通函数相同。构造函数也可以当做普通函数来用，这种直接在全局作用域调用构造函数时函数中的this对象指向Global对象（在浏览器中就是window对象），也可以在某个特殊对象的作用域中使用<code>call()</code>或者<code>apply()</code>调用这个构造函数。</p>
<p>构造函数主要的问题在于构造函数中的方法在每个实例上都重新创建了一遍，可以将方法放到构造函数外部，但这不符全局作用域（全局函数只能被某个对象调用）并且如果方法很多就要定义多个全局函数（毫无封装性）。</p>
</li>
<li><p>原型模式</p>
<p>每个函数都有一个prototype属性，可以让所有对象实例共享它所包含的属性和方法。原型对象中<code>constructor</code>属性指回构造函数。</p>
<p>调用构造函数创建一个新实例后，该实例内部将包含一个指针<code>[[Prototype]]</code>（<s>Firefox、Safari、Chrome在每个对象中的<code>__proto__</code>属性，其他实现中这个属性对脚本不可见</s>）指向构造函数的原型对象，可以通过<code>Constructor.prototype.isPrototypeOf(instance)</code>确定对象之间是否存在这种关系或者<code>Object.getPrototypeOf(instance)</code>返回<code>[[Prototype]]</code>的值。</p>
<p>js 中所有的对象都有 <code>__proto__</code> 属性，指向构造该对象构造函数的原型，只有函数 function 才具有 prototype 属性，指向原型对象。</p>
<pre class=" language-javascript"><code class="language-javascript"><span class="token comment" spellcheck="true">// 函数对象都是由Function函数生成的：</span>
<span class="token keyword">function</span> <span class="token function">fn</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span><span class="token punctuation">}</span>
fn<span class="token punctuation">.</span>__proto__ <span class="token operator">===</span> Function<span class="token punctuation">.</span>prototype
<span class="token comment" spellcheck="true">// Function函数本身作为对象时，生成它的函数是他自身！</span>
Function<span class="token punctuation">.</span>__proto__ <span class="token operator">===</span> Function<span class="token punctuation">.</span>prototype
<span class="token comment" spellcheck="true">// Object函数既然是函数，那生成它的函数自然是Function函数咯：</span>
Object<span class="token punctuation">.</span>__proto__ <span class="token operator">===</span> Function<span class="token punctuation">.</span>prototype
Object<span class="token punctuation">.</span>prototype<span class="token punctuation">.</span>__proto <span class="token operator">===</span> <span class="token keyword">null</span>
</code></pre>
<p>读取对象某个属性会进行一次搜索，从对象实例开始沿着原型链搜索，直到找到该属性或者到原型链的末尾。当在对象实例上添加属性时，这个属性就会屏蔽原型对象中保存的同名属性。</p>
<p><code>for-in</code>循环返回的是所有能够通过对象访问的、可枚举（enumerated）的属性，既包括存在实例中也包括存在原型中的属性，屏蔽了原型中不可枚举属性（即将<code>[[Enumerable]]</code>标记为false的属性）的实例属性也会在for-in循环中返回（IE8及更早的版本除外）。这里使用node和chrome进行了测试发现只要将enumerated属性设置为false就会无法在for-in循环中取得相应的属性。</p>
<p><code>Object.keys</code>取得对象上所有可枚举的实例属性。<code>Object.getOwnPropertyNames()</code>返回所有的属性（无论可枚举但不会进行原型链的查找）。</p>
<p>每创建一个函数就会同时创建它的<code>prototype</code>对象，这个对象也会自动获得<code>constructor</code>属性，以对象字面量的形式重写原型对象<code>constructor</code>属性也就变成了新对象的constructor属性（指向Object构造函数），可以显式的在对象字面量中指定。同时重写原型对象会切断实例与最初原型对象之间的联系（实例中的<code>[[Prototype]]</code>仅指向原型而不指向原型对象）。</p>
<p>原型对象主要的问题在于包含引用类型值的属性，所有的实例中都会共享这一个属性值。</p>
</li>
<li><p>组合使用构造函数模式和原型模式</p>
<p>构造函数模式用于定义实例属性，原型模式用于定义方法和共享的属性。</p>
<blockquote>
<p>如果在原型中和构造函数中都定义同名实例属性，构造函数中的实例属性会覆盖原型中的实例属性值。</p>
</blockquote>
<p>将引用类型放到构造函数中可以解决引用类型被共享的问题，同时保留了原型定义共享方法的优点。是目前在ECMAScript中使用最广泛、认同度最高的一种创建自定义类型的方法。</p>
</li>
<li><p>动态原型模式</p>
<p>将独立的构造函数和原型封装到构造函数中，在构造函数中进行原型方法的初始化（通过<code>typeof</code>或<code>instanceof</code>检查原型中是否存在某个方法来决定是否对其进行初始化操作，即只会初始化一次）。</p>
</li>
<li><p>寄生构造函数模式</p>
<p>构造函数的外形（函数生命和使用方式，通过new操作符使用），函数内部使用工厂模式，可以用来封装定制特定方法的对象（无法修改原始对象的原型），返回的对象与构造函数或者与构造函数的原型属性之间没有关系。</p>
</li>
<li><p>稳妥构造函数模式</p>
<p>稳妥对象，没有公共属性，其方法不引用this对象，适用于安全环境中（禁止使用this和new）或防止程序被其他应用程序改动时使用。稳妥构造函数模式和寄生构造函数模式类似，不同之处在于新创建对象的实例方法中不使用this、不使用new操作符调用构造函数，需要注意的是这种模式中只有函数中的方法才能访问传入到构造函数中的数据成员。</p>
</li>
</ol>
<h3 id="继承"><a href="#继承" class="headerlink" title="继承"></a>继承</h3><ol>
<li><p>原型链</p>
<p>通过创建父类型的实例，然后将子类型的原型指向这个实例。<strong>修改原型后需要注意原型上的构造函数也被更改了，需要改回：<code>subType.prototype.constructor = subType</code></strong></p>
<p>所有引用类型默认都继承了Object，所有函数的默认原型都是Object的实例。</p>
<p>确定原型和实例之间的关系：<code>instanceof</code>用来测试实例与原型链中出现过的构造函数，<code>isPrototypeOf</code>原型链中是否可以派生出该实例的原型。</p>
<p>子类型重写原型之中的同名方法后，子类型的实例调用该方法就会是重新定义后的方法，父类型的实例调用该方法仍是原来的那个方法（可以看做是一种屏蔽）。</p>
<p>原型链继承主要的问题就是包含引用类型值的原型属性会被所有实例共享。</p>
</li>
<li><p>借用构造函数</p>
<p>解决原型中包含引用类型值所带来的的问题：在子类型构造函数的内部“借调”超类型构造函数（同时也可向其中传递参数），即通过<code>apply()</code>或<code>call()</code>方法在新将要创建的子类实例中调用父类型构造函数（在创建的子类实例对象上执行父类型构造函数中定义的所有对象初始化代码）。</p>
<p>借用构造函数的问题：父类型原型中定义的方法和属性对于子类型不可见；方法需要在构造函数中定义（无法实现函数复用）。</p>
</li>
<li><p><strong>组合继承</strong>（最常用的继承模式）</p>
<p>使用原型链实现对原型属性和方法的继承，借用构造函数实现对实例属性的继承。</p>
<p>组合继承的问题在于无论什么情况下都会调用两次超类型构造函数：第一次是在创建子类型原型的时候即<code>SubType.prototype = new SuperType()</code>，<code>SubType.prototype</code>会得到<code>SuperType</code>实例属性；第二次是在子类型构造函数内部，<code>new SubType()</code>会调用<code>SuperType.call(this)</code>，新对象会获得<code>SuperType</code>实例属性，就会屏蔽掉原型中同名属性。</p>
</li>
<li><p>原型式继承</p>
<p>借助原型基于已有的对象创建新对象。</p>
<pre><code>function object(o){ // 对其中的方法执行了一次浅复制
    function F(){}
    F.prototype = o;
    return new F();
}
</code></pre><p>ECMAScript5中的<code>Object.create()</code>方法是对<code>object()</code>函数的规范化（行为相同），包含引用类型值的属性始终都会共享相应的值。</p>
</li>
<li><p>寄生式继承</p>
<p>和工厂模式类似（函数结构和调用方式），内部首先创建一个继承原型的对象（可以通过原型式继承的方式），对这个对象可以以某种方式来增强对象最后再返回这个对象。这种模式没有解决引用类型的问题。</p>
</li>
<li><p><strong>寄生组合式继承</strong>（引用类型最理想的继承范式）</p>
<p>解决组合继承中调用两次超类型构造函数的问题：通过借用构造函数来继承属性，通过原型链的混成形式来继承方法。即用寄生式继承方式继承超类型的类型（指定子类型的原型不采用调用超类型构造函数的形式），然后在将结果指定给子类型的原型。</p>
<pre><code>function inheritPrototype (subType, superType) {
    var prototype = object(superType.prototype); // 创建超类型原型的一个副本
    prototype.constructor = subType; // 为创建的副本添加constructor属性
                                     // 重写原型失去了默认的constructor属性
    subType.prototype = prototype;     // 将副本赋值给子类型的原型
}

function SuperType(){...}
function SubType(){
    SuperType.call(this);
}
inheritPrototype(SubType, SuperType);
</code></pre></li>
</ol>
<blockquote>
<p><a href="https://juejin.im/post/58f94c9bb123db411953691b#heading-10" target="_blank" rel="noopener">扩展</a></p>
</blockquote>
<h3 id="new"><a href="#new" class="headerlink" title="new"></a>new</h3><p>ECMAScript语言规范中new运算符的定义：</p>
<blockquote>
<p>The production NewExpression : new NewExpression is evaluated as follows:</p>
<ol>
<li>Evaluate NewExpression.</li>
<li>Call GetValue(Result(1)).</li>
<li>If Type(Result(2)) is not Object, throw a TypeError exception.</li>
<li>If Result(2) does not implement the internal [<a href="http://www.pushiming.com/blog/2009/10/the-new-operator/#appendix" target="_blank" rel="noopener">[Construct]]</a> method, throw a TypeError exception.</li>
<li>Call the [[Construct]] method on Result(2), providing no arguments (that is, an empty list of arguments).</li>
<li>Return Result(5).</li>
</ol>
</blockquote>
<ul>
<li>注意到，这段定义中的 new 后的表达式不带参数</li>
</ul>
<p>new 后必须跟一个对象并且此对象必须有一个名为 [[Construct]] 的内部方法（其实这种对象就是构造器），否则会抛出异常，如果符合以上条件，那么引擎将调用其 [[Construct]] 内部方法，并不提供入口参数。</p>
<blockquote>
<p>[[Construct]]内部方法：</p>
<p>When the [[Construct]] property for a Function object F is called, the following steps are taken:</p>
<ol>
<li>Create a new native ECMAScript object.</li>
<li>Set the [<a href="http://www.pushiming.com/blog/2009/10/the-new-operator/#appendix" target="_blank" rel="noopener">[Class]]</a> property of Result(1) to “Object”.</li>
<li>Get the value of the prototype property of the F.</li>
<li>If Result(3) is an object, set the [<a href="http://www.pushiming.com/blog/2009/10/the-new-operator/#appendix" target="_blank" rel="noopener">[Prototype]]</a> property of Result(1) to Result(3).</li>
<li>If Result(3) is not an object, set the [[Prototype]] property of Result(1) to the original Object prototype object as described in 15.2.3.1.</li>
<li>Invoke the [<a href="http://www.pushiming.com/blog/2009/10/the-new-operator/#appendix" target="_blank" rel="noopener">[Call]]</a> property of F, providing Result(1) as the this value and providing the argument list passed into [[Construct]] as the argument values.</li>
<li>If Type(Result(6)) is Object then return Result(6).</li>
<li>Return Result(1).</li>
</ol>
</blockquote>
<p>引擎将先创建一个语言原生对象，即“{}”或“new Object”，在此我们称之为 O，然后设置其内部属性标识 [[Class]] 为“Object”。接下来，得到构造器 F 的 prototype（根据后文的意思，它可能不是一个对象）。如果 F.prototype 是对象，那么将 O 的内部 [[Prototype]] 属性指向 F.prototype。</p>
<p>请注意，诸如 [[Prototype]] 等为引擎内部标识符，对我们并不可见。[[Prototype]] 正是用于给内部维护原型链，虽然在我们看来，一个对象实例无法直接回溯到其原型（然而引擎内部可以），必须通过构造器中转，即 obj.constructor.prototype。</p>
<p>接着，如果 F.prototype 不是 object，那么将 O 的内部 [[Prototype]] 属性指向“the Object prototype object”。等到 O 的 [[Prototype]] 有了自己的归属以后，引擎调用构造器 F 的 [[Call]] 内部方法，以 O 作为 this 对象，并将传入 [[Construct]] 的参数作为入口参数——如果有的话（即诸如“new Object()”最后括号内的参数）传递过去。最后，如果 [[Call]] 的返回值是对象，那么创建成功并返回此对象，否则回头重来。</p>
<p>可以构造一个伪 [[Construct]] 方法来模拟此流程：</p>
<pre class=" language-js"><code class="language-js"><span class="token keyword">function</span> <span class="token function">MyObject</span><span class="token punctuation">(</span>age<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span>age <span class="token operator">=</span> age<span class="token punctuation">;</span>
<span class="token punctuation">}</span>

MyObject<span class="token punctuation">.</span>construct <span class="token operator">=</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">var</span> o <span class="token operator">=</span> <span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">,</span> Constructor <span class="token operator">=</span> MyObject<span class="token punctuation">;</span>
    o<span class="token punctuation">.</span>__proto__ <span class="token operator">=</span> Constructor<span class="token punctuation">.</span>prototype<span class="token punctuation">;</span>
    <span class="token comment" spellcheck="true">// FF 支持用户引用内部属性 [[Prototype]]</span>
    Constructor<span class="token punctuation">.</span><span class="token function">apply</span><span class="token punctuation">(</span>o<span class="token punctuation">,</span> arguments<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">return</span> o
<span class="token punctuation">}</span><span class="token punctuation">;</span>

<span class="token keyword">var</span> obj1 <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">MyObject</span><span class="token punctuation">(</span><span class="token number">10</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> obj2 <span class="token operator">=</span> MyObject<span class="token punctuation">.</span><span class="token function">construct</span><span class="token punctuation">(</span><span class="token number">10</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">alert</span><span class="token punctuation">(</span>obj2 <span class="token keyword">instanceof</span> <span class="token class-name">MyObject</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment" spellcheck="true">// true</span>

<span class="token comment" spellcheck="true">// es6 写法</span>
<span class="token keyword">function</span> New <span class="token punctuation">(</span>fn<span class="token punctuation">,</span> <span class="token operator">...</span>args<span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">var</span> obj <span class="token operator">=</span> Object<span class="token punctuation">.</span><span class="token function">create</span><span class="token punctuation">(</span>fn<span class="token punctuation">.</span>prototype<span class="token punctuation">)</span>
  fn<span class="token punctuation">.</span><span class="token function">call</span><span class="token punctuation">(</span>obj<span class="token punctuation">,</span> <span class="token operator">...</span>args<span class="token punctuation">)</span>
  <span class="token keyword">return</span> obj
<span class="token punctuation">}</span>
<span class="token comment" spellcheck="true">// es5 写法</span>
<span class="token keyword">function</span> New <span class="token punctuation">(</span>fn<span class="token punctuation">,</span> <span class="token operator">...</span>args<span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">var</span> obj <span class="token operator">=</span> <span class="token punctuation">{</span><span class="token punctuation">}</span>
  obj<span class="token punctuation">.</span>__proto__ <span class="token operator">=</span> fn<span class="token punctuation">.</span>prototype
  fn<span class="token punctuation">.</span><span class="token function">call</span><span class="token punctuation">(</span>obj<span class="token punctuation">,</span> <span class="token operator">...</span>args<span class="token punctuation">)</span>
  <span class="token keyword">return</span> obj
<span class="token punctuation">}</span>
</code></pre>
<h4 id="箭头函数"><a href="#箭头函数" class="headerlink" title="箭头函数"></a>箭头函数</h4><p>可以通过 <code>console.dir</code> 发现箭头函数没有 prototype 属性（无 constructor），不能使用 arguments 属性</p>
<p>箭头函数不能使用 new 操作符</p>

      
    </div>
    
    
    

    

    

    

    <footer class="post-footer">
      

      
      
      

      
        <div class="post-nav">
          <div class="post-nav-next post-nav-item">
            
              <a href="/2019/09/27/css-haslayout/" rel="next" title="hasLayout">
                <i class="fa fa-chevron-left"></i> hasLayout
              </a>
            
          </div>

          <span class="post-nav-divider"></span>

          <div class="post-nav-prev post-nav-item">
            
              <a href="/2019/10/01/css-layout/" rel="prev" title="css中几种常见布局设计">
                css中几种常见布局设计 <i class="fa fa-chevron-right"></i>
              </a>
            
          </div>
        </div>
      

      
      
    </footer>
  </div>
  
  
  
  </article>



    <div class="post-spread">
      
    </div>
  </div>


          </div>
          


          

  
    <div class="comments" id="comments">
    </div>
  



        </div>
        
          
  
  <div class="sidebar-toggle">
    <div class="sidebar-toggle-line-wrap">
      <span class="sidebar-toggle-line sidebar-toggle-line-first"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-middle"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-last"></span>
    </div>
  </div>

  <aside id="sidebar" class="sidebar">
    
    <div class="sidebar-inner">

      

      
        <ul class="sidebar-nav motion-element">
          <li class="sidebar-nav-toc sidebar-nav-active" data-target="post-toc-wrap">
            文章目录
          </li>
          <li class="sidebar-nav-overview" data-target="site-overview-wrap">
            站点概览
          </li>
        </ul>
      

      <section class="site-overview-wrap sidebar-panel">
        <div class="site-overview">
          <div class="site-author motion-element" itemprop="author" itemscope="" itemtype="http://schema.org/Person">
            
              <p class="site-author-name" itemprop="name">renhao</p>
              <p class="site-description motion-element" itemprop="description"></p>
          </div>

          <nav class="site-state motion-element">

            
              <div class="site-state-item site-state-posts">
              
                <a href="/archives/">
              
                  <span class="site-state-item-count">94</span>
                  <span class="site-state-item-name">日志</span>
                </a>
              </div>
            

            
              
              
              <div class="site-state-item site-state-categories">
                <a href="/categories/index.html">
                  <span class="site-state-item-count">19</span>
                  <span class="site-state-item-name">分类</span>
                </a>
              </div>
            

            

          </nav>

          
            <div class="feed-link motion-element">
              <a href="/atom.xml" rel="alternate">
                <i class="fa fa-rss"></i>
                RSS
              </a>
            </div>
          

          

          
          

          
          

          

        </div>
      </section>

      
      <!--noindex-->
        <section class="post-toc-wrap motion-element sidebar-panel sidebar-panel-active">
          <div class="post-toc">

            
              
            

            
              <div class="post-toc-content"><ol class="nav"><li class="nav-item nav-level-3"><a class="nav-link" href="#理解对象"><span class="nav-number">1.</span> <span class="nav-text">理解对象</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#创建对象"><span class="nav-number">2.</span> <span class="nav-text">创建对象</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#继承"><span class="nav-number">3.</span> <span class="nav-text">继承</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#new"><span class="nav-number">4.</span> <span class="nav-text">new</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#箭头函数"><span class="nav-number">4.1.</span> <span class="nav-text">箭头函数</span></a></li></ol></li></ol></div>
            

          </div>
        </section>
      <!--/noindex-->
      

      

    </div>
  </aside>


        
      </div>
    </main>

    <footer id="footer" class="footer">
      <div class="footer-inner">
        <div class="copyright">&copy; <span itemprop="copyrightYear">2020</span>
  <span class="with-love">
    <i class="fa fa-user"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">renhao</span>

  
    <span class="post-meta-divider">|</span>
    <span class="post-meta-item-icon">
      <i class="fa fa-area-chart"></i>
    </span>
    
      <span class="post-meta-item-text">Site words total count&#58;</span>
    
    <span title="Site words total count">265.9k</span>
  
</div>


  <div class="powered-by">由 <a class="theme-link" target="_blank" href="https://hexo.io">Hexo</a> 强力驱动</div>



  <span class="post-meta-divider">|</span>



  <div class="theme-info">主题 &mdash; <a class="theme-link" target="_blank" href="https://github.com/iissnan/hexo-theme-next">NexT.Muse</a> v5.1.4</div>




        







        
      </div>
    </footer>

    
      <div class="back-to-top">
        <i class="fa fa-arrow-up"></i>
        
      </div>
    

    

  </div>

  

<script type="text/javascript">
  if (Object.prototype.toString.call(window.Promise) !== '[object Function]') {
    window.Promise = null;
  }
</script>









  












  
  
    <script type="text/javascript" src="/lib/jquery/index.js?v=2.1.3"></script>
  

  
  
    <script type="text/javascript" src="/lib/fastclick/lib/fastclick.min.js?v=1.0.6"></script>
  

  
  
    <script type="text/javascript" src="/lib/jquery_lazyload/jquery.lazyload.js?v=1.9.7"></script>
  

  
  
    <script type="text/javascript" src="/lib/velocity/velocity.min.js?v=1.2.1"></script>
  

  
  
    <script type="text/javascript" src="/lib/velocity/velocity.ui.min.js?v=1.2.1"></script>
  

  
  
    <script type="text/javascript" src="/lib/fancybox/source/jquery.fancybox.pack.js?v=2.1.5"></script>
  


  


  <script type="text/javascript" src="/js/src/utils.js?v=5.1.4"></script>

  <script type="text/javascript" src="/js/src/motion.js?v=5.1.4"></script>



  
  

  
  <script type="text/javascript" src="/js/src/scrollspy.js?v=5.1.4"></script>
<script type="text/javascript" src="/js/src/post-details.js?v=5.1.4"></script>



  


  <script type="text/javascript" src="/js/src/bootstrap.js?v=5.1.4"></script>



  


  




	





  





  










  <script src="//cdn1.lncld.net/static/js/3.0.4/av-min.js"></script>
  <script src="//unpkg.com/valine/dist/Valine.min.js"></script>
  
  <script type="text/javascript">
    var GUEST = ['nick','mail','link'];
    var guest = 'nick,mail,link';
    guest = guest.split(',').filter(item=>{
      return GUEST.indexOf(item)>-1;
    });
    new Valine({
        el: '#comments' ,
        verify: false,
        notify: false,
        appId: '2P1xqUWiCoNm14MH4yhURlJi-gzGzoHsz',
        appKey: 'uJN0uagHIVgXtBO1OuLV9Ban',
        placeholder: 'Just go go',
        avatar:'mm',
        guest_info:guest,
        pageSize:'10' || 10,
    });
  </script>



  





  

  

  

  
  

  

  

  

</body>
</html>
